<?php
namespace app\user\model;

use think\Model;
use think\facade\Cookie;
use app\ucenter\facade\UCenterApi;
use app\user\validate\PasswordValidate;
use Utils\PasswordHash;

class User extends Model {
    protected $pk = 'uid';

    protected function initialize(): void {
        parent::initialize();
    }

    public static function getRealEmail(string $email): ?string {
        list($username, $domain) = explode('@', $email);
        if($domain === 'isekai.top' || $domain === 'isekai.cn'){
            return null;
        } else {
            return $email;
        }
    }

    /**
     * 生成用户的登录token
     * @return string token
     */
    public function generateToken(){
        //获取用户的基本token（不对外显示的隐藏token，必要时可以重置以在其他设备上登出）
        if (empty($this->getData('token'))) {
            $baseToken = md5(uniqid());
            $this->setAttr('token', $baseToken);
            $this->save();
        } else {
            $baseToken = $this->getData('token');
        }
        $uid = $this->getData('uid');
        //生成验证登录使用的token
        $salt = hex2bin(rand_hex(8));
        $token = hash_hmac('md5', hex2bin($baseToken), $salt, true);
        $token = base64_encode(int2bin($uid) . $salt . $token);
        return $token;
    }

    /**
     * 设置登录token
     * @param boolean $keepLogin 保持登录（记住密码）
     * @return void
     */
    public function setLogin($keepLogin = false, $clientIp = NULL) {
        $token = $this->generateToken();
        if ($keepLogin == false) {
            Cookie::set('login', $token);
        } else {
            Cookie::set('login', $token, 604800);
        }

        // 更新登录相关的信息
        $this->setLoginData($clientIp);
    }

    /**
     * 设置登录的信息
     */
    public function setLoginData($clientIp = NULL){
        if(is_null($clientIp)){
            $clientIp = get_client_ip();
        }

        $this->setAttr('last_login_ip', $clientIp);
        $this->setAttr('last_login_time', mysql_current_datetime());
    }

    /**
     * 验证token
     * @param string $token
     * @return bool 是否验证通过
     */
    public function verifyToken($salt, $token){
        $baseToken = $this->getData('token');
        return $token == hash_hmac('md5', hex2bin($baseToken), $salt, true);
    }

    /**
     * 通过uid和token获取用户
     * @param int $uid
     * @param string $token
     * @return User 获取到的用户
     */
    public static function getByToken($tokenData) {
        $tokenData = base64_decode($tokenData);
        $uid = bin2int(substr($tokenData, 0, 4));
        $salt = substr($tokenData, 4, 4);
        $token = substr($tokenData, 8);
        $UserData = self::get($uid);
        if($UserData == null){
            Cookie::delete('login');
            return self::getGuest();
        }
        if($UserData->verifyToken($salt, $token)){
            return $UserData;
        } else {
            Cookie::delete('login');
            return self::getGuest();
        }
    }

    public function setPasswordAttr($password): string {
        $hashMethod = PasswordValidate::defaultMethod;
        $methodName = PasswordValidate::class . '::generate' . parse_name($hashMethod, 1);
        $this->setAttr('hash_method', $hashMethod);
        $result = call_user_func($methodName, $password);
        return $result;
    }

    public function checkPassword($input): bool {
        $hash = $this->getData('password');
        $method = $this->getData('hash_method');
        if(!empty($hash)){
            $methodName = PasswordValidate::class . '::compare' . parse_name($method, 1);
            if(is_callable($methodName)){
                $result = call_user_func($methodName, $hash, $input);
                if($result){
                    if(in_array($method, PasswordValidate::needUpgrade)){ //升级加密方式
                        $this->setAttr('password', $input);
                        $this->save();
                    }
                    return true;
                } else {
                    return false;
                }
            }
        } else {
            return false;
        }
    }

    /**
     * 创建一个虚拟的游客用户
     * @return User 用户
     */
    public static function getGuest() {
        $UserData = new User([
            'uid' => -1,
            'username' => lang('游客'),
            'token' => '',
            'email' => '',
            'password' => '',
        ]);
        return $UserData;
    }

    /**
     * 创建一个虚拟的被删除用户
     * @return User 用户
     */
    public static function getDeleted() {
        $UserData = new User([
            'uid' => -2,
            'username' => lang('账号已注销'),
            'access' => self::DELETED,
            'token' => '',
            'money' => 0,
            'coin' => 0,
            'email' => 'no-reply@pdcgame.com',
            'password' => '',
        ]);
        return $UserData;
    }
}